
#include "lib_mpp.h"

#include "../lib_ffmpeg/lib_ffmpeg.h"

//****************************************************************

static  RKMPPCodecContext g_mpp_ctx;


static pthread_t  pMpp_decode_thread;
static pthread_t  pMpp_timer_thread;

static int        avpacket_index = 0;

static int        mpp_new_frame     = 0;
static int        de_frame_time     = 1000;
static int64_t    v_pts_time        = 0;
//****************************************************************

int mpp_para_deinit(void)
{
	avpacket_index  =  0;

	return 0;
}

//****************************************************************

int mpp_decode_h264(uint8_t *temp_data,int size,int pts)
{
	int mode	  = 0;
	int spsLength = 0;
	int ppsLength = 0;
	int nalLength = 0;
	
	uint8_t* ex = NULL;
	uint8_t*  first_packet_buff = NULL;
	uint64_t  first_packet_len	= 0;

	AVPacket tmpPacket;

	if(!temp_data)
		return -1;
	
	if(!size)
		return -1;

	RKMPPCodecContext *mpp_ctx = &g_mpp_ctx;

	uint8_t  startCode[4]	= { 0x00, 0x00, 0x00, 0x01};

	if(memcmp(startCode, temp_data, 4) != 0)
	{		
		if(mode != 2){
			mode = 2;log_n(" avc\n");
		}
		if(avpacket_index == 0)
		{
			avpacket_index = 1;

			ffmpeg_get_extradata(&ex);

			if(ex){
				spsLength = (ex[6] << 8) | ex[7];
				ppsLength = (ex[8 + spsLength + 1] << 8) | ex[8 + spsLength + 2];
	
				first_packet_len = spsLength + ppsLength + size + 8;
	
				first_packet_buff = malloc(first_packet_len);
				if(first_packet_buff){
					memset(first_packet_buff,0,first_packet_len);
				}

				memcpy(first_packet_buff, startCode, 4);
				memcpy(first_packet_buff+4,  ex + 8, spsLength);
	
				memcpy(first_packet_buff+4+spsLength, startCode, 4);
				memcpy(first_packet_buff+4+spsLength+4, ex + 8 + spsLength + 2 + 1, ppsLength);
	
				memcpy(first_packet_buff+spsLength+ppsLength+8, temp_data, size);
			}

			uint8_t* data = temp_data;
			while(data < temp_data + size){
				nalLength = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
				if (nalLength > 0) {
					memcpy(data, startCode, 4); 
				}
				data = data + 4 + nalLength; 
			}

			memcpy(first_packet_buff+4+spsLength+4+ppsLength, temp_data, size);

			temp_data = first_packet_buff;
			size = first_packet_len;
				
			decode_one_pkt(mpp_ctx,temp_data,size,pts);

			if(first_packet_buff){
				free(first_packet_buff);
				first_packet_buff = NULL;
			}
		}
		else
		{			
			uint8_t* data = temp_data;
			while (data < temp_data + size)
			{
				nalLength = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | data[3];
				if (nalLength > 0) {
					memcpy(data, startCode, 4); 	
				}
				data = data + 4 + nalLength;	
			}
					
			decode_one_pkt(mpp_ctx,temp_data,size,pts);
		}
	}
	else
	{
		if(mode != 1){
			mode = 1;log_n("h264\n");
		}
		decode_one_pkt(mpp_ctx,temp_data,size,pts);
	}	

	return 0;
}
void* mpp_timer_task(void *arg)
{

	struct timeval timer;	

	while(1)
	{
		usleep(1000);

		timer.tv_sec  = 0;
		timer.tv_usec = de_frame_time*1000;

		switch(select(0, NULL, NULL, NULL, &timer)) {
		case -1:  
			log_e("Error!\n");
			break;
		case 0:
			break;
		default:
			break;
		}
	}
}


//****************************************************************
void* mpp_decode_thread(void *arg)
{

	long	  s_time = 0;
	long	  e_time = 0;

	int       ret = -1;
	int       packet_size = 0;
	int64_t   packet_pts  = 0;
	int64_t   packet_dts  = 0;
	uint8_t * packet_data = NULL;


	while(1)
	{
		usleep(100);
		//***************************************************************
		if(ffmpeg_is_stop()){
			ffmpeg_set_video_stop(1);
			mpp_new_frame = 0;
			continue;
		}
		//***************************************************************
		ffmpeg_set_video_stop(0);
		if(queue_packet_video_is_empty()){
			continue;
		}
		//***************************************************************
		if(!mpp_new_frame)
		{
			ret = queue_packet_read_video(&packet_data,&packet_size,&packet_pts,&packet_dts);
			if(ret!=0){
				continue;
			}
			mpp_new_frame   = 1;
			v_pts_time      = ffmpeg_get_v_clock(packet_pts);
			v_pts_time      = v_pts_time ;
		}
		//***************************************************************
		if(ffmpeg_sync_time_get() < v_pts_time)
		{
			continue;
		}
		//***************************************************************
		mpp_decode_h264(packet_data,packet_size,packet_pts);
		//***************************************************************
		mpp_new_frame = 0;
		//***************************************************************
	}
}



//****************************************************************

int lib_mpp_init(void)
{	
	int ret = -1;

	log_n("lib mpp init.\n");

    rkmpp_decoder_init(&g_mpp_ctx);

	ret=pthread_create(&pMpp_decode_thread,NULL,mpp_decode_thread,NULL);
	if(ret != 0){
		log_e("thread error=%s\n",strerror(ret));
	}

	ret=pthread_create(&pMpp_timer_thread, NULL, mpp_timer_task, NULL);
	if(ret != 0){
		log_e("thread error=%s\n",strerror(ret));
	}


	return 0;
}


int lib_mpp_deinit(void)
{
	log_n("lib mpp exit.\n");






	return 0;
}


